#ifndef COMPARATOR_TEST_H_INCLUDED
#define COMPARATOR_TEST_H_INCLUDED

#include "Comparator.h"
#include <assert.h>
#include <iostream>
#include <string.h>

template<class T>
class Comparator_Test
{
public:
    static void runTest();
    Comparator_Test();
    void test();

private:
    Comparator comp;

    static bool smaller(char* one, char* other);
    static bool smallerOrEqual(char* one, char* other);
    static bool greater(char* one, char* other);
    static bool greaterOrEqual(char* one, char* other);
    static bool equal(char* one, char* other);

    static T random();
};

template<class T> void Comparator_Test<T>::runTest()
{
    srand(time(0));

    cout << "Start Comparator_Test<int>" << endl;
    Comparator_Test<int> t1;
    t1.test();
    cout << "End Comparator_Test<int>" << endl;

    cout << "Start Comparator_Test<long>" << endl;
    Comparator_Test<long> t2;
    t2.test();
    cout << "End Comparator_Test<long>" << endl;

    cout << "Start Comparator_Test<string>" << endl;
    Comparator_Test<string> t3;
    t3.test();
    cout << "End Comparator_Test<string>" << endl;
}

template<class T> Comparator_Test<T>::Comparator_Test() : comp(&smaller, &smallerOrEqual, &greater, &greaterOrEqual, &equal)
{
}

template<class T> void Comparator_Test<T>::test()
{
    for (unsigned i = 0; i < 10000; i++)
    {
        T x = random();
        T y = random();

        Segment& s = DB::getDB().getSegmentManager().createSegment();
        NodeContext n(0, comp, s);
        Comparator comp2 = n.compare;

        assert(comp2(SMALLER, (char*)&x, (char*)&y) == (x < y));
        assert(comp2(SMALLEROREQUAL, (char*)&x, (char*)&y) == (x <= y));
        assert(comp2(GREATER, (char*)&x, (char*)&y) == (x > y));
        assert(comp2(GREATEROREQUAL, (char*)&x, (char*)&y) == (x >= y));
        assert(comp2(EQUAL, (char*)&x, (char*)&y) == (x == y));
    }
}

template<> int Comparator_Test<int>::random()
{
    return rand();
}

template<> long Comparator_Test<long>::random()
{
    return (long)rand();
}

template<> string Comparator_Test<string>::random()
{
    char blubb[20];
    for (unsigned i = 0; i < 20; i++)
    {
        blubb[i] = rand();
    }
    return string(blubb);
}

template<class T> bool Comparator_Test<T>::smaller (char* one, char* other)
{
    return *((T*)one) < *((T*)other);
}

template<class T> bool Comparator_Test<T>::smallerOrEqual (char* one, char* other)
{
    return *((T*)one) <= *((T*)other);
}

template<class T> bool Comparator_Test<T>::greater (char* one, char* other)
{
    return *((T*)one) > *((T*)other);
}

template<class T> bool Comparator_Test<T>::greaterOrEqual (char* one, char* other)
{
    return *((T*)one) >= *((T*)other);
}

template<class T> bool Comparator_Test<T>::equal (char* one, char* other)
{
    return *((T*)one) == *((T*)other);
}

#endif // COMPARATOR_TEST_H_INCLUDED
